namespace cpputils
{

struct noncopyable
{
	noncopyable() {};
private:
	noncopyable(const noncopyable&);
	noncopyable& operator=(const noncopyable&);
};

struct scoped_va_list : private noncopyable
{
	va_list ptr;

	~scoped_va_list()
	{
		va_end(ptr);
	}
};

template<class T>
inline const typename T::value_type* begin_ptr(const T& V)
{
	if (V.empty()) return 0;
	return &V.front();
}

template<class T>
inline const typename T::value_type* end_ptr(const T& V)
{
	if (V.empty()) return 0;
	return &V.back() + 1;
}

template<class T>
inline typename T::value_type* begin_ptr(T& V)
{
	if (V.empty()) return 0;
	return &V.front();
}

template<class T>
inline typename T::value_type* end_ptr(T& V)
{
	if (V.empty()) return 0;
	return &V.back() + 1;
}

template<class T>
void reset_vector(vector<T>& V)
{
	vector<T>().swap(V);
}

template<class T>
void pack_vector(vector<T>& V)
{
	if (V.capacity() > V.size()) vector<T>(V).swap(V);
}

template<class T>
void reset_string(basic_string<T>& V)
{
	basic_string<T>().swap(V);
}

template<class T>
void pack_string(basic_string<T>& V)
{
	if (V.capacity() > V.size()) basic_string<T>(V).swap(V);
}

template<class T>
T& to_nonconst(const T& V)
{
	return const_cast<T&>(V);
}

template<class T, class TT>
void assign_if_less(T& Val, const TT& Other)
{
	if (Other < Val) Val = Other;
}

template<class T, class TT>
void assign_if_greater(T& Val, const TT& Other)
{
	if (Other > Val) Val = Other;
}

string to_string(int V);
string to_string(unsigned int V);
string to_string(long long V);
string to_string(unsigned long long V);
int to_int(const string& S);
unsigned int to_unsigned_int(const string& S);
long long to_long_long(const string& S);
unsigned long long to_unsigned_long_long(const string& S);

string to_string(float V);
string to_string(double V);
float to_float(const string& S);
double to_double(const string& S);

string format_string(const char* Fmt, va_list Args);
string format_string(const char* Fmt, ...);

vector<string> split_string(const string& S, char Ch);

int checked_fprintf(FILE* File, const char* Fmt, va_list Args);
int checked_fprintf(FILE* File, const char* Fmt, ...);
int checked_printf(const char* Fmt, va_list Args);
int checked_printf(const char* Fmt, ...);
FILE* checked_fopen(const string& Filename, const string& Mode);

string change_filename_ext(string S, const string& Ext);

}
